/*
 * Copyright (c) 2023 Cshoo Org. All Rights Reserved.
 */

package org.cshoo.tattoo.authorize.domain.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.IteratorUtils;
import org.cshoo.tattoo.authorize.domain.po.*;
import org.cshoo.tattoo.authorize.domain.repository.IGroupRepository;
import org.cshoo.tattoo.authorize.domain.repository.IGroupRoleRelationRepository;
import org.cshoo.tattoo.authorize.domain.repository.IGroupUserRelationRepository;
import org.cshoo.tattoo.embed.infra.utils.UserUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author 杨翼
 * @since 1.0
 */
@Slf4j
@Service
public class GroupService {

    @Resource
    private UserService userService;

    @Resource
    private RoleService roleService;

    @Resource
    private IGroupRepository groupRepository;

    @Resource
    private IGroupUserRelationRepository groupUserRelationRepository;

    @Resource
    private IGroupRoleRelationRepository groupRoleRelationRepository;

    /**
     * 添加一个群组
     *
     * @param group 群组对象
     */
    public void addGroup(Group group) {
        groupRepository.save(group);
    }

    /**
     * 在群组中增加一个新用户
     *
     * @param groupId 群组id
     * @param user    用户
     */
    public void addNewUser(Long groupId, User user) {
        List<User> dbUsers = userService.findUserByName(user.getUsername());
        if (CollectionUtils.isNotEmpty(dbUsers)) {
            User dbUser = dbUsers.get(0);
            user.setId(dbUser.getId());
        } else {
            userService.addUser(user);
        }
        this.addExistingUser(groupId, user.getId());
    }

    /**
     * 添加现有用户
     *
     * @param groupId 群组id
     * @param userId  用户id
     */
    public void addExistingUser(Long groupId, Long userId) {
        GroupUserRelation groupUserRelation = new GroupUserRelation();
        groupUserRelation.setGroupId(groupId);
        groupUserRelation.setUserId(userId);
        groupUserRelationRepository.save(groupUserRelation);
    }

    /**
     * 新建一个新角色并关联到指定群组
     *
     * @param groupId 指定群组id
     * @param role    角色信息
     */
    @Transactional
    public void addNewRole(Long groupId, Role role) {
        Role dbRole = roleService.findRoleByName(role.getName());
        if (Objects.nonNull(dbRole)) {
            role.setId(dbRole.getId());
        } else {
            roleService.addRole(role);
        }
        this.assignExistingRole(groupId, role.getId());
    }

    /**
     * 分配一个现有的角色
     *
     * @param groupId 群组id
     * @param roleId  角色id
     */
    public void assignExistingRole(Long groupId, Long roleId) {
        GroupRoleRelation groupRoleRelation = new GroupRoleRelation();
        groupRoleRelation.setGroupId(groupId);
        groupRoleRelation.setRoleId(roleId);
        groupRoleRelationRepository.save(groupRoleRelation);
    }

    /**
     * 解除一个角色
     *
     * @param groupId 群组id
     * @param roleId  角色id
     */
    public void dismissRole(Long groupId, Long roleId) {
        groupRoleRelationRepository.deleteGroupRoleRelationByGroupIdAndRoleId(groupId, roleId);
    }

    /**
     * 移除一个用户
     *
     * @param groupId 群组id
     * @param userId  用户id
     */
    public void removeUser(Long groupId, Long userId) {
        groupUserRelationRepository.deleteByGroupIdAndUserId(groupId, userId);
    }

    /**
     * 修改一个群组
     * 这里只修改基本信息，
     * 当不传角色的时候不修群组对应的角色，防止将角色清空
     *
     * @param group 群组
     */
    public void updateGroup(Group group) {
        group.setLastModifiedBy(UserUtils.getUser().getUsername());
        group.setLastModifiedDate(new Date());
        groupRepository.updateGroup(group);
    }

    /**
     * 查询所有群组
     *
     * @return 群组
     */
    @SuppressWarnings("unchecked")
    public List<Group> findAllGroup() {
        Iterable<Group> groupIterable = groupRepository.findAll();
        return IteratorUtils.toList(groupIterable.iterator());
    }

    /**
     * 删除一个群组
     *
     * @param id 群组id
     */
    public void deleteGroup(Long id) {
        groupRepository.deleteById(id);
    }

}
